package com.jzo2o.market.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.common.expcetions.BadRequestException;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.common.model.PageResult;
import com.jzo2o.common.utils.*;
import com.jzo2o.market.constants.TabTypeConstants;
import com.jzo2o.market.enums.ActivityStatusEnum;
import com.jzo2o.market.enums.CouponStatusEnum;
import com.jzo2o.market.mapper.ActivityMapper;
import com.jzo2o.market.model.domain.Activity;
import com.jzo2o.market.model.domain.Coupon;
import com.jzo2o.market.model.dto.request.ActivityQueryForPageReqDTO;
import com.jzo2o.market.model.dto.request.ActivitySaveReqDTO;
import com.jzo2o.market.model.dto.response.ActivityInfoResDTO;
import com.jzo2o.market.model.dto.response.SeizeCouponInfoResDTO;
import com.jzo2o.market.service.IActivityService;
import com.jzo2o.market.service.ICouponService;
import com.jzo2o.market.service.ICouponWriteOffService;
import com.jzo2o.mvc.utils.UserContext;
import com.jzo2o.mysql.utils.PageUtils;

import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static com.jzo2o.market.constants.RedisConstants.RedisKey.*;
import static com.jzo2o.market.enums.ActivityStatusEnum.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author itcast
 * @since 2023-09-16
 */
@Service
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements IActivityService {
    private static final int MILLION = 1000000;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private ICouponService couponService;

    @Resource
    private ICouponWriteOffService couponWriteOffService;

    @Resource
    private ActivityMapper baseMapper;

    /**
     * 添加优惠券活动
     *
     * @param reqDTO 添加参数
     */
    @Override
    public void saveActivity(ActivitySaveReqDTO reqDTO) {
        Activity activity = new Activity();

        if (LocalDateTime.now().isAfter(reqDTO.getDistributeStartTime())) {
            throw new CommonException("活动开始时间不能在当前时间之前");
        }
        if (reqDTO.getDistributeStartTime().isAfter(reqDTO.getDistributeEndTime())) {
            throw new CommonException("活动结束时间不能在开始时间之前");
        }
        if (reqDTO.getDistributeEndTime().isBefore(LocalDateTime.now())) {
            throw new CommonException("活动结束时间在当前时间之前");
        }

        BeanUtils.copyProperties(reqDTO, activity);
        activity.setStatus(NO_DISTRIBUTE.getStatus());
        activity.setUpdateBy(UserContext.currentUserId());
        activity.setCreateBy(UserContext.currentUserId());
        activity.setStockNum(reqDTO.getTotalNum());
        // 如果id 有值需判断状态SF在发放中，禁止修改
        if (reqDTO.getId() != null) {
            Activity activityById = super.getById(reqDTO.getId());
            if (activityById.getStatus().equals(DISTRIBUTING.getStatus())) {
                throw new CommonException("活动正在发放中，禁止操作");
            }
        }

        super.saveOrUpdate(activity);
    }

    /**
     * 获取优惠券活动列表
     *
     * @param reqDTO 获取参数
     * @return 优惠券活动列表
     */
    @Override
    public PageResult<ActivityInfoResDTO> pageActivityPage(ActivityQueryForPageReqDTO reqDTO) {
        Page<Activity> activityPage = PageUtils.parsePageQuery(reqDTO, Activity.class);
        LambdaQueryWrapper<Activity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .like(StringUtils.hasText(reqDTO.getName()), Activity::getName, reqDTO.getName())
                .eq(reqDTO.getStatus() != null, Activity::getStatus, reqDTO.getStatus())
                .eq(reqDTO.getType() != null, Activity::getType, reqDTO.getType())
                .eq(Activity::getIsDeleted, 0);
        activityPage = super.page(activityPage, queryWrapper);
        return PageUtils.toPage(activityPage, ActivityInfoResDTO.class);
    }

    @Override
    public ActivityInfoResDTO getByActivityId(Long id) {
        Activity byId = super.getById(id);
        ActivityInfoResDTO activityInfoResDTO = BeanUtils.toBean(byId, ActivityInfoResDTO.class);
        // 核销数量
        int usedCount = couponService.count(Wrappers.<Coupon>lambdaQuery().eq(Coupon::getStatus, CouponStatusEnum.USED.getStatus()));
        // 领取数量
        int receiveCount = couponService.count(Wrappers.<Coupon>lambdaQuery().eq(Coupon::getActivityId, id));

        activityInfoResDTO.setReceiveNum(receiveCount);

        activityInfoResDTO.setWriteOffNum(usedCount);
        //
        return activityInfoResDTO;
    }

    @Override
    public void revokeActivity(Long id) {
        //修改活动状态为撤销
        Activity activity = super.getById(id);
        if (activity == null) {
            throw new BadRequestException("活动不存在");
        }
        if (!activity.getStatus().equals(DISTRIBUTING.getStatus())) {
            throw new BadRequestException("活动状态不是发放中，不能撤销");
        }
        activity.setStatus(VOIDED.getStatus());
        super.updateById(activity);
    }

    @Override
    public int updateActivityStock(Long id, int i) {
        Activity activity = super.getById(id);
        if(activity == null || activity.getDistributeStartTime().isAfter(DateUtils.now())){
            throw new CommonException("活动未开始");
        }
        if(activity.getDistributeEndTime().isBefore(DateUtils.now())){
            throw new CommonException("活动已结束");
        }


        return baseMapper.updateStock(id, i);
    }

    @Override
    public Activity queryActivityFromCacheById(Long id) {
        Object activityList = redisTemplate.opsForValue().get(ACTIVITY_CACHE_LIST);
        if(activityList == null){
            return null;
        }
        List<Activity> list = JsonUtils.toList(activityList.toString(),Activity.class);
        //查找指定活动
        Activity activity = list.stream().filter(a -> a.getId().equals(id)).findFirst().orElse(null);
        return activity;
    }

}
